package com.cencat.route.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cencat.route.entity.Route;
import com.cencat.route.mapper.RouteMapper;
import com.cencat.route.service.RouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 路由服务实现类
 * 
 * @author cencat
 * @version 1.0
 * @since 2024-12-19
 */
@Service
@Transactional
public class RouteServiceImpl extends ServiceImpl<RouteMapper, Route> implements RouteService {

    @Autowired
    private RouteMapper routeMapper;

    @Override
    public IPage<Route> getRoutePage(Page<Route> page, Integer routeStatus, LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.selectRoutePage(page, routeStatus, startTime, endTime);
    }

    @Override
    public List<Route> getRoutesByPoints(java.math.BigDecimal startLatitude, java.math.BigDecimal startLongitude,
                                        java.math.BigDecimal endLatitude, java.math.BigDecimal endLongitude, Integer limit) {
        return routeMapper.selectRoutesByPoints(startLatitude, startLongitude, endLatitude, endLongitude, limit);
    }

    @Override
    public Route getRouteByCode(String routeCode) {
        return routeMapper.selectRouteByCode(routeCode);
    }

    @Override
    public List<Route> getPopularRoutes(Integer limit, Integer days) {
        return routeMapper.selectPopularRoutes(limit, days);
    }

    @Override
    public List<Route> getRecentRoutes(Long userId, Integer limit) {
        return routeMapper.selectRecentRoutes(userId, limit);
    }

    @Override
    public boolean createRoute(Route route) {
        // 生成路由编码
        route.setRouteCode(generateRouteCode());
        route.setCreateTime(LocalDateTime.now());
        route.setUpdateTime(LocalDateTime.now());
        route.setRouteStatus(1); // 默认状态为启用
        return save(route);
    }

    @Override
    public Long countRoutes(Integer routeStatus, LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.countRoutes(routeStatus, startTime, endTime);
    }

    @Override
    public List<Map<String, Object>> getRouteStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.selectRouteStatistics(startTime, endTime);
    }

    @Override
    public boolean updateRouteStatus(Long routeId, Integer routeStatus, LocalDateTime updateTime) {
        return routeMapper.updateRouteStatus(routeId, routeStatus, updateTime) > 0;
    }

    @Override
    public boolean updateRouteUsageCount(Long routeId, Integer usageCount, LocalDateTime updateTime) {
        return routeMapper.updateRouteUsageCount(routeId, usageCount, updateTime) > 0;
    }

    @Override
    public boolean batchUpdateRouteStatus(List<Long> routeIds, Integer routeStatus, LocalDateTime updateTime) {
        return routeMapper.batchUpdateRouteStatus(routeIds, routeStatus, updateTime) > 0;
    }

    @Override
    public Map<String, Object> getRouteUsageStats(Long routeId, LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.selectRouteUsageStats(routeId, startTime, endTime);
    }

    @Override
    public Map<String, Object> getRoutePerformanceStats(Long routeId, LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.selectRoutePerformanceStats(routeId, startTime, endTime);
    }

    @Override
    public Map<String, Object> getRouteRatingStats(Long routeId, LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.selectRouteRatingStats(routeId, startTime, endTime);
    }

    @Override
    public List<Map<String, Object>> getRouteRanking(Integer rankType, LocalDateTime startTime, 
                                                    LocalDateTime endTime, Integer limit) {
        return routeMapper.selectRouteRanking(rankType, startTime, endTime, limit);
    }

    @Override
    public List<Map<String, Object>> getSmartRouteRecommendation(Long userId, java.math.BigDecimal startLatitude, 
                                                                java.math.BigDecimal startLongitude, java.math.BigDecimal endLatitude, 
                                                                java.math.BigDecimal endLongitude, Map<String, Object> preferences, Integer limit) {
        return routeMapper.selectSmartRouteRecommendation(userId, startLatitude, startLongitude, endLatitude, endLongitude, preferences, limit);
    }

    @Override
    public Map<String, Object> getRouteCongestionInfo(Long routeId, LocalDateTime currentTime) {
        return routeMapper.selectRouteCongestionInfo(routeId, currentTime);
    }

    @Override
    public boolean updateRouteCongestionStatus(Long routeId, Integer congestionLevel, LocalDateTime updateTime) {
        return routeMapper.updateRouteCongestionStatus(routeId, congestionLevel, updateTime) > 0;
    }

    @Override
    public java.math.BigDecimal calculateRouteDistance(java.math.BigDecimal startLatitude, java.math.BigDecimal startLongitude,
                                                      java.math.BigDecimal endLatitude, java.math.BigDecimal endLongitude) {
        // 使用Haversine公式计算两点间距离
        double lat1Rad = Math.toRadians(startLatitude.doubleValue());
        double lon1Rad = Math.toRadians(startLongitude.doubleValue());
        double lat2Rad = Math.toRadians(endLatitude.doubleValue());
        double lon2Rad = Math.toRadians(endLongitude.doubleValue());
        
        double deltaLat = lat2Rad - lat1Rad;
        double deltaLon = lon2Rad - lon1Rad;
        
        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
                  Math.cos(lat1Rad) * Math.cos(lat2Rad) *
                  Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
        
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double earthRadius = 6371; // 地球半径（公里）
        
        return java.math.BigDecimal.valueOf(earthRadius * c);
    }

    @Override
    public Integer estimateRouteTime(Long routeId, LocalDateTime currentTime, java.math.BigDecimal trafficFactor) {
        Route route = getById(routeId);
        if (route == null) {
            return 0;
        }
        
        // 基础时间估算（假设平均速度40km/h）
        java.math.BigDecimal distance = route.getRouteDistance();
        if (distance == null) {
            return 0;
        }
        
        double baseTime = distance.doubleValue() / 40.0 * 60; // 转换为分钟
        double adjustedTime = baseTime * trafficFactor.doubleValue();
        
        return (int) Math.round(adjustedTime);
    }

    @Override
    public List<Map<String, Object>> getRouteHistoryData(Long routeId, LocalDateTime startTime, LocalDateTime endTime) {
        return routeMapper.selectRouteHistoryData(routeId, startTime, endTime);
    }

    @Override
    public Map<String, Object> optimizeRoute(Long routeId, Integer optimizationType) {
        return routeMapper.selectOptimizedRoute(routeId, optimizationType);
    }

    @Override
    public List<Map<String, Object>> getAlternativeRoutes(java.math.BigDecimal startLatitude, java.math.BigDecimal startLongitude,
                                                         java.math.BigDecimal endLatitude, java.math.BigDecimal endLongitude, Integer limit) {
        return routeMapper.selectAlternativeRoutes(startLatitude, startLongitude, endLatitude, endLongitude, limit);
    }

    @Override
    public boolean updateRouteRating(Long routeId, java.math.BigDecimal rating, LocalDateTime updateTime) {
        return routeMapper.updateRouteRating(routeId, rating, updateTime) > 0;
    }

    @Override
    public boolean addRouteFavorite(Long userId, Long routeId, LocalDateTime createTime) {
        return routeMapper.insertRouteFavorite(userId, routeId, createTime) > 0;
    }

    @Override
    public boolean removeRouteFavorite(Long userId, Long routeId) {
        return routeMapper.deleteRouteFavorite(userId, routeId) > 0;
    }

    @Override
    public List<Route> getUserFavoriteRoutes(Long userId, Integer limit) {
        return routeMapper.selectUserFavoriteRoutes(userId, limit);
    }

    @Override
    public Map<String, Object> getRouteDetailInfo(Long routeId) {
        return routeMapper.selectRouteDetailInfo(routeId);
    }

    @Override
    public boolean batchImportRoutes(List<Route> routes) {
        if (routes == null || routes.isEmpty()) {
            return false;
        }
        
        LocalDateTime now = LocalDateTime.now();
        for (Route route : routes) {
            if (route.getRouteCode() == null) {
                route.setRouteCode(generateRouteCode());
            }
            route.setCreateTime(now);
            route.setUpdateTime(now);
            if (route.getRouteStatus() == null) {
                route.setRouteStatus(1);
            }
        }
        
        return saveBatch(routes);
    }

    @Override
    public List<Map<String, Object>> exportRouteData(List<Long> routeIds) {
        return routeMapper.selectRouteExportData(routeIds);
    }

    @Override
    public boolean syncRouteData(Integer syncType, LocalDateTime lastSyncTime) {
        return routeMapper.syncRouteData(syncType, lastSyncTime) > 0;
    }

    @Override
    public boolean cleanExpiredRoutes(Integer expireDays) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(expireDays);
        return routeMapper.deleteExpiredRoutes(expireTime) > 0;
    }

    /**
     * 生成路由编码
     * 
     * @return 路由编码
     */
    private String generateRouteCode() {
        return "RT" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }

}